package com.qiusuo0226.setup;

import com.qiusuo0226.common.util.BeanContext;
import com.qiusuo0226.mysql.service.DatabaseService;
import com.qiusuo0226.platform.annotation.SysUpgrade;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 系统升级处理类
 * 系统启动后会自动调用该类，扫描被注册的方法，按order顺序一个个检测过去，直到升级到最新
 * @author qiusuo
 * @date 2024/3/15 10:40
 */
@Slf4j
@Order(1)
@Component
public class UpgradeHandler implements CommandLineRunner {

    @Autowired
    private DatabaseService databaseService;

    @SysUpgrade(developer = "qiusuo0226",
            version = "1.0.0",
            order = 0,
            description = {"初始化项目", "初始化项目系统模块表结构"})
    public void version100() {
        // resources文件夹下的路径
        databaseService.executeSqlScript("setup/sqls/V1.0.0.sql");
    }

    @SysUpgrade(developer = "qiusuo0226",
            version = "1.0.1",
            order = 1,
            description = {"初始化项目核心模块表结构", "初始化核心模块表数据"})
    public void version101() {
        // resources文件夹下的路径
        databaseService.executeSqlScript("setup/sqls/V1.0.1.sql");
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("<<<<<<<<<< 项目初始化:stat ----------");
        // 所有标注了@SysUpgrade注解的方法
        List<Method> upgradeMethods = new ArrayList<>();
        // 获取UpgradeHandler所有的方法（私有、公有、保护）
        Class<UpgradeHandler> upgradeHandlerClass = UpgradeHandler.class;
        Method[] declaredMethods = upgradeHandlerClass.getDeclaredMethods();
        // 遍历：所有的方法，找出使用了@SysUpgrade注解的方法
        for (Method method : declaredMethods) {
            if (method.isAnnotationPresent(SysUpgrade.class)) {
                upgradeMethods.add(method);
            }
        }

        // 排序：对使用了@SysUpgrade注解的方法根据注解中的order属性进行从小到大的排序
        Collections.sort(upgradeMethods, new Comparator<Method>() {
            @Override
            public int compare(Method o1, Method o2) {
                // 获取两个方法上的注解
                SysUpgrade annotation1 = o1.getAnnotation(SysUpgrade.class);
                SysUpgrade annotation2 = o2.getAnnotation(SysUpgrade.class);

                int order1 = annotation1.order();
                int order2 = annotation2.order();

                if (order1 > order2) {
                    return 1;
                } else if (order1 < order2) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });

        UpgradeHandler upgradeHandler = BeanContext.getBean(UpgradeHandler.class);

        // 将排序好的方法一个个执行
        for (Method method:upgradeMethods) {
            // 执行项目版本升级方法
            method.invoke(upgradeHandler);
        }
        log.info("<<<<<<<<<< 项目初始化:end ----------");
    }
}
